package com.github.fancyideas.controller;

import com.github.fancyideas.module.dto.ShoesSaveDTO;
import com.github.fancyideas.module.dto.ShoesTakeOutDTO;
import com.github.fancyideas.module.entity.CustomerEntity;
import com.github.fancyideas.module.entity.ShoesEntity;
import com.github.fancyideas.module.entity.ShoesHisEntity;
import com.github.fancyideas.repository.CustomerRepository;
import com.github.fancyideas.repository.ShoesHisRepository;
import com.github.fancyideas.repository.ShoesRepository;
import com.github.fancyideas.utils.Result;
import com.github.fancyideas.utils.ResultBuilder;
import com.github.fancyideas.utils.UpdateWithoutNull;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.Predicate;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Api(value = "鞋子信息", tags = {"客户的鞋子信息"})
@RestController
@RequestMapping("/shoes")
public class ShoesController {

    @Autowired
    private ShoesHisRepository shoesHisRepository;

    @Autowired
    private ShoesRepository shoesRepository;

    @Autowired
    private CustomerRepository customerRepository;

    @ApiOperation(value = "鞋子信息（翻页）", notes = "根据客户Id")
    @GetMapping("/page/{pageNo}/{pageSize}")
    public Page<ShoesEntity> listAll(@PathVariable int pageNo,
                                     @PathVariable int pageSize,
                                     @RequestParam Long customerId) {
        pageNo = pageNo - 1;
        Pageable pageable = PageRequest.of(pageNo, pageSize, Sort.Direction.ASC, "customerId");
        Page<ShoesEntity> customerViewPage = shoesRepository.findAll(
                (Specification<ShoesEntity>) (root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    list.add(criteriaBuilder.equal(root.get("customerId").as(Long.class), customerId));
                    Predicate[] p = new Predicate[list.size()];
                    return criteriaBuilder.and(list.toArray(p));
                }, pageable);
        return customerViewPage;
    }

    @ApiOperation(value = "添加鞋子/客户信息", notes = "如果客户之前添加过，那么只添加鞋子信息，否则同时添加")
    @Transactional
    @PostMapping
    public Result save(@RequestBody ShoesSaveDTO shoesSaveDTO) throws InvocationTargetException, IllegalAccessException {
        // 如果customerId 为空。那么是新用户
        CustomerEntity customerEntity = new CustomerEntity();
        ShoesEntity shoesEntity = new ShoesEntity();
        BeanUtils.copyProperties(shoesEntity, shoesSaveDTO);
        if (shoesSaveDTO.getCustomerId() == null) {
            BeanUtils.copyProperties(customerEntity, shoesSaveDTO);
            customerEntity = customerRepository.save(customerEntity);
            shoesEntity.setCustomerId(customerEntity.getCustomerId());
        }
        shoesRepository.save(shoesEntity);
        return ResultBuilder.buildSuccess(shoesSaveDTO);
    }

    @ApiOperation(value = "修改鞋子信息", notes = "根据Id修改鞋子信息")
    @PutMapping("/{shoesId}")
    public Result update(@PathVariable Long shoesId,
                         @RequestBody ShoesEntity shoesEntity) {
        ShoesEntity shoesResult =
                new UpdateWithoutNull<ShoesRepository, ShoesEntity>()
                        .updateParameterWithoutNull(shoesRepository, shoesEntity, shoesId);
        return ResultBuilder.buildSuccess(shoesResult);
    }

    @ApiOperation(value = "取走鞋子信息", notes = "取走鞋子ID根据鞋子，并存入历史表")
    @Transactional
    @DeleteMapping("/{shoesId}")
    public Result takeOut(@PathVariable Long shoesId,
                          @RequestBody ShoesTakeOutDTO shoesTakeOutDTO) throws InvocationTargetException, IllegalAccessException {
        // 获取鞋子信息
        ShoesEntity shoesEntity = shoesRepository.getOne(shoesId);
        ShoesHisEntity shoesHisEntity = new ShoesHisEntity();
        BeanUtils.copyProperties(shoesHisEntity, shoesEntity);
        shoesHisEntity.setCost(shoesTakeOutDTO.getMoney());
        shoesHisEntity.setTakeOutDate(shoesTakeOutDTO.getTakeOutDate());
        // 存入历史表
        shoesHisRepository.save(shoesHisEntity);
        shoesRepository.deleteById(shoesId);
        return ResultBuilder.buildSuccess(shoesId);
    }

    @ApiOperation(value = "替换鞋子信息", notes = "新的鞋子信息替换旧的，旧的鞋子信息存入历史表")
    @Transactional
    @PostMapping("replace/{oldShoesId}")
    public Result replace(@PathVariable Long oldShoesId,
                          @RequestBody ShoesHisEntity newShoesEntity) throws InvocationTargetException, IllegalAccessException {
        // 获取鞋子信息
        ShoesEntity oldShoesEntity = shoesRepository.getOne(oldShoesId);
        ShoesHisEntity shoesHisEntity = new ShoesHisEntity();
        BeanUtils.copyProperties(shoesHisEntity, oldShoesEntity);
        // 旧鞋子存入历史表
        shoesHisEntity.setTakeOutDate(newShoesEntity.getTakeOutDate());
        shoesHisEntity.setCost(newShoesEntity.getCost());
        shoesHisRepository.save(shoesHisEntity);
        shoesRepository.deleteById(oldShoesId);
        // 新鞋子信息保存
        ShoesEntity saveShoesEntity = new ShoesEntity();
        BeanUtils.copyProperties(saveShoesEntity, newShoesEntity);
        shoesRepository.save(saveShoesEntity);
        return ResultBuilder.buildSuccess(newShoesEntity);
    }

}
